using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Engine;
using Engine.Graphics;
using Game;

namespace RuthlessConquest {
    public class GameSetupScreen : Screen {
        public enum GameType {
            Internet,
            Local
        }

        public class GameTypeWidget : StackPanelWidget {
            public GameTypeWidget(GameType gameType) {
                HorizontalAlignment = WidgetAlignment.Center;
                VerticalAlignment = WidgetAlignment.Center;
                Direction = LayoutDirection.Vertical;
                Margin = new Vector2(100f, 0f);
                Children.Add(
                    new LabelWidget {
                        Text = GetGameTypeName(gameType),
                        Color = Colors.Fore,
                        Margin = new Vector2(0f, 3f),
                        HorizontalAlignment = WidgetAlignment.Center
                    }
                );
                Children.Add(
                    new LabelWidget {
                        HorizontalAlignment = WidgetAlignment.Center,
                        Text = GetGameTypeDescription(gameType),
                        Color = Colors.ForeDim,
                        FontScale = 0.75f,
                        WordWrap = true,
                        TextAnchor = TextAnchor.HorizontalCenter
                    }
                );
            }
        }

        /*public static readonly int[] NeutralPopulationFactors = [
            25,
            50,
            75,
            100,
            200,
            400,
            600
        ];

        public static readonly int[] SpecialEventsFrequency = [
            50,
            60,
            70,
            80,
            90,
            100,
            110,
            120,
            130
        ];*/

        public LabelWidget TrueWorldSeedLabel;
        public RectangleWidget PreviewRectangle;
        public ButtonWidget UpdatePreviewButton;
        public ButtonWidget GameTypeButton;
        public SliderWidget PlayersCountSlider;
        public SliderWidget PlanetsCountSlider;
        public SliderWidget SpecialPlanetsCountSlider;
        public SliderWidget NeutralsPopulationSlider;
        public SliderWidget SpecialEventsSlider;
        public BevelledButtonWidget AILevelButton;
        public BevelledButtonWidget ShipRangeButton;
        public BevelledButtonWidget WorldSeedButton;
        public ButtonWidget PlayButton;
        public ButtonWidget BackButton;
        public GameType publicGameType;
        public PlayerType AILevel = PlayerType.EasyAI;
        public ShipRange ShipRange = ShipRange.Short;
        public string WorldSeed = string.Empty;
        public int TrueWorldSeed;
        public Random Random = new();
        public const string fName = "RCGameSetupScreen";

        public GameSetupScreen() {
            Widget[] rootChildren = [new BackgroundWidget(), new BoidsWidget(), new InterlaceWidget(), null];
            StackPanelWidget rootPanel = new() {
                Direction = LayoutDirection.Vertical,
                Margin = new Vector2(20f, 0f),
                Children = {
                    new CanvasWidget { Size = new Vector2(0f, 10f) },
                    new CanvasWidget {
                        Size = new Vector2(float.PositiveInfinity, -1f),
                        Children = {
                            new LabelWidget {
                                Text = LanguageControl.Get(fName, "1"),
                                FontScale = 0.75f,
                                Color = Colors.Fore,
                                HorizontalAlignment = WidgetAlignment.Center
                            }
                        }
                    },
                    new CanvasWidget { Size = new Vector2(0f, 10f) }
                }
            };
            CanvasWidget mainCanvas = new() {
                Size = new Vector2(float.PositiveInfinity, float.PositiveInfinity), Children = { new RectangleWidget(), new InterlaceWidget() }
            };
            ScrollPanelWidget scrollPanel = new() { Direction = LayoutDirection.Vertical, Margin = new Vector2(2f, 2f) };
            StackPanelWidget optionsPanel = new() { Direction = LayoutDirection.Vertical };
            TrueWorldSeedLabel = new LabelWidget { HorizontalAlignment = WidgetAlignment.Center, FontScale = 0.75F, Color = Color.LightGray };
            UniformSpacingPanelWidget previewPanel = new() {
                Margin = new Vector2(0f, 3f),
                Children = {
                    new StackPanelWidget {
                        Direction = LayoutDirection.Vertical,
                        HorizontalAlignment = WidgetAlignment.Far,
                        VerticalAlignment = WidgetAlignment.Center,
                        Children = {
                            new LabelWidget {
                                Text = LanguageControl.Get(PracticeSetupScreen.fName, "15"),
                                HorizontalAlignment = WidgetAlignment.Far,
                                Margin = new Vector2(20f, 5f)
                            },
                            TrueWorldSeedLabel
                        }
                    }
                }
            };
            StackPanelWidget previewRightPanel = new() { Margin = new Vector2(20f, 0f) };
            CanvasWidget previewRightCanvas = new() { Margin = new Vector2(20f, 0f), Size = new Vector2(float.PositiveInfinity, -1f) };
            PreviewRectangle = new RectangleWidget {
                Size = new Vector2(256f, 144f),
                HorizontalAlignment = WidgetAlignment.Center,
                FillColor = Color.White,
                OutlineColor = Color.Transparent
            };
            previewRightCanvas.Children.Add(PreviewRectangle);
            previewRightPanel.Children.Add(previewRightCanvas);
            UpdatePreviewButton = new BevelledButtonWidget {
                VerticalAlignment = WidgetAlignment.Center,
                Size = new Vector2(60f, 60f),
                Children = {
                    new RectangleWidget {
                        HorizontalAlignment = WidgetAlignment.Center,
                        VerticalAlignment = WidgetAlignment.Center,
                        Size = new Vector2(28f, 28f),
                        Subtexture = ContentManager.Get<Subtexture>("Textures/Gui/UpdateChecking"),
                        FillColor = Color.White,
                        OutlineColor = Color.Transparent,
                        TextureLinearFilter = true,
                        TextureAnisotropicFilter = true,
                        BlendState = BlendState.NonPremultiplied
                    }
                }
            };
            previewRightPanel.Children.Add(UpdatePreviewButton);
            previewPanel.Children.Add(previewRightPanel);
            optionsPanel.Children.Add(previewPanel);
            UniformSpacingPanelWidget obj6 = new() {
                Margin = new Vector2(0f, 3f),
                Children = {
                    new LabelWidget {
                        Text = LanguageControl.Get(fName, "2"),
                        HorizontalAlignment = WidgetAlignment.Far,
                        VerticalAlignment = WidgetAlignment.Center,
                        Margin = new Vector2(20f, 0f)
                    }
                }
            };
            GameTypeButton = new BevelledButtonWidget {
                Margin = new Vector2(20f, 0f),
                HorizontalAlignment = WidgetAlignment.Near,
                VerticalAlignment = WidgetAlignment.Center,
                Size = new Vector2(float.PositiveInfinity, 60f)
            };
            obj6.Children.Add(GameTypeButton);
            optionsPanel.Children.Add(obj6);
            UniformSpacingPanelWidget obj8 = new() {
                Margin = new Vector2(0f, 3f),
                Children = {
                    new LabelWidget {
                        Text = LanguageControl.Get(PracticeSetupScreen.fName, "2"),
                        HorizontalAlignment = WidgetAlignment.Far,
                        VerticalAlignment = WidgetAlignment.Center,
                        Margin = new Vector2(20f, 0f)
                    }
                }
            };
            AILevelButton = new BevelledButtonWidget {
                Margin = new Vector2(20f, 0f),
                HorizontalAlignment = WidgetAlignment.Near,
                VerticalAlignment = WidgetAlignment.Center,
                Size = new Vector2(float.PositiveInfinity, 60f)
            };
            obj8.Children.Add(AILevelButton);
            optionsPanel.Children.Add(obj8);
            UniformSpacingPanelWidget obj10 = new() {
                Margin = new Vector2(0f, 3f),
                Children = {
                    new LabelWidget {
                        Text = LanguageControl.Get(PracticeSetupScreen.fName, "3"),
                        HorizontalAlignment = WidgetAlignment.Far,
                        VerticalAlignment = WidgetAlignment.Center,
                        Margin = new Vector2(20f, 0f)
                    }
                }
            };
            ShipRangeButton = new BevelledButtonWidget {
                Margin = new Vector2(20f, 0f),
                HorizontalAlignment = WidgetAlignment.Near,
                VerticalAlignment = WidgetAlignment.Center,
                Size = new Vector2(float.PositiveInfinity, 60f)
            };
            obj10.Children.Add(ShipRangeButton);
            optionsPanel.Children.Add(obj10);
            UniformSpacingPanelWidget obj12 = new() {
                Margin = new Vector2(0f, 3f),
                Children = {
                    new LabelWidget {
                        Text = LanguageControl.Get(PracticeSetupScreen.fName, "4"),
                        HorizontalAlignment = WidgetAlignment.Far,
                        VerticalAlignment = WidgetAlignment.Center,
                        Margin = new Vector2(20f, 0f)
                    }
                }
            };
            WorldSeedButton = new BevelledButtonWidget {
                Margin = new Vector2(20f, 0f),
                HorizontalAlignment = WidgetAlignment.Near,
                VerticalAlignment = WidgetAlignment.Center,
                Size = new Vector2(float.PositiveInfinity, 60f)
            };
            obj12.Children.Add(WorldSeedButton);
            optionsPanel.Children.Add(obj12);
            UniformSpacingPanelWidget obj14 = new() {
                Margin = new Vector2(0f, 3f),
                Children = {
                    new LabelWidget {
                        Text = LanguageControl.Get(PracticeSetupScreen.fName, "5"),
                        HorizontalAlignment = WidgetAlignment.Far,
                        VerticalAlignment = WidgetAlignment.Center,
                        Margin = new Vector2(20f, 0f)
                    }
                }
            };
            PlayersCountSlider = new SliderWidget { MinValue = 2f, MaxValue = 6f, Granularity = 1f, Margin = new Vector2(20f, 0f) };
            obj14.Children.Add(PlayersCountSlider);
            optionsPanel.Children.Add(obj14);
            UniformSpacingPanelWidget obj16 = new() {
                Margin = new Vector2(0f, 3f),
                Children = {
                    new LabelWidget {
                        Text = LanguageControl.Get(PracticeSetupScreen.fName, "6"),
                        HorizontalAlignment = WidgetAlignment.Far,
                        VerticalAlignment = WidgetAlignment.Center,
                        Margin = new Vector2(20f, 0f)
                    }
                }
            };
            SpecialEventsSlider = new SliderWidget { MinValue = 10f, MaxValue = 500f, Granularity = 10f, Margin = new Vector2(20f, 0f) };
            obj16.Children.Add(SpecialEventsSlider);
            optionsPanel.Children.Add(obj16);
            UniformSpacingPanelWidget obj18 = new() {
                Margin = new Vector2(0f, 3f),
                Children = {
                    new LabelWidget {
                        Text = LanguageControl.Get(PracticeSetupScreen.fName, "7"),
                        HorizontalAlignment = WidgetAlignment.Far,
                        VerticalAlignment = WidgetAlignment.Center,
                        Margin = new Vector2(20f, 0f)
                    }
                }
            };
            PlanetsCountSlider = new SliderWidget { MinValue = 4f, MaxValue = 64f, Granularity = 1f, Margin = new Vector2(20f, 0f) };
            obj18.Children.Add(PlanetsCountSlider);
            optionsPanel.Children.Add(obj18);
            UniformSpacingPanelWidget obj20 = new() {
                Margin = new Vector2(0f, 3f),
                Children = {
                    new LabelWidget {
                        Text = LanguageControl.Get(PracticeSetupScreen.fName, "8"),
                        HorizontalAlignment = WidgetAlignment.Far,
                        VerticalAlignment = WidgetAlignment.Center,
                        Margin = new Vector2(20f, 0f)
                    }
                }
            };
            SpecialPlanetsCountSlider = new SliderWidget { MinValue = 0f, MaxValue = 20f, Granularity = 1f, Margin = new Vector2(20f, 0f) };
            obj20.Children.Add(SpecialPlanetsCountSlider);
            optionsPanel.Children.Add(obj20);
            UniformSpacingPanelWidget obj22 = new() {
                Margin = new Vector2(0f, 3f),
                Children = {
                    new LabelWidget {
                        Text = LanguageControl.Get(PracticeSetupScreen.fName, "9"),
                        HorizontalAlignment = WidgetAlignment.Far,
                        VerticalAlignment = WidgetAlignment.Center,
                        Margin = new Vector2(20f, 0f)
                    }
                }
            };
            NeutralsPopulationSlider = new SliderWidget { MinValue = 0f, MaxValue = 1500f, Granularity = 25f, Margin = new Vector2(20f, 0f) };
            obj22.Children.Add(NeutralsPopulationSlider);
            optionsPanel.Children.Add(obj22);
            scrollPanel.Children.Add(optionsPanel);
            mainCanvas.Children.Add(scrollPanel);
            rootPanel.Children.Add(mainCanvas);
            rootPanel.Children.Add(new CanvasWidget { Size = new Vector2(0f, 20f) });
            StackPanelWidget obj24 = new() { Direction = LayoutDirection.Horizontal, HorizontalAlignment = WidgetAlignment.Center };
            PlayButton = new BevelledButtonWidget {
                Text = LanguageControl.Get(PracticeSetupScreen.fName, "10"), Size = new Vector2(300f, 60f), Margin = new Vector2(20f, 0f)
            };
            obj24.Children.Add(PlayButton);
            BackButton = new BevelledButtonWidget {
                Text = LanguageControl.Back, Size = new Vector2(200f, 60f), Margin = new Vector2(20f, 0f), Sound = "RCSounds/Click2"
            };
            obj24.Children.Add(BackButton);
            rootPanel.Children.Add(obj24);
            rootPanel.Children.Add(new CanvasWidget { Size = new Vector2(0f, 10f) });
            rootChildren[3] = rootPanel;
            Children.Add(rootChildren);
            scrollPanel.ScrollPosition = 0f;
            PlayersCountSlider.Value = 6f;
            PlanetsCountSlider.Value = 24f;
            SpecialPlanetsCountSlider.Value = 3f;
            NeutralsPopulationSlider.Value = 100f;
            SpecialEventsSlider.Value = 100f;
            scrollPanel.ScrollPosition = 0f;
            TrueWorldSeed = Random.Int();
        }

        public override void Enter(object[] parameters) {
            if (string.IsNullOrEmpty(WorldSeed)) {
                TrueWorldSeed = Random.Int();
                UpdatePreview();
            }
            if (ScreensManager.m_animationData.OldScreen is not GameListScreen) {
                ServersManager.StartServerDiscovery();
            }
        }

        public override void Leave() {
            if (ScreensManager.m_animationData.NewScreen is not GameListScreen) {
                ServersManager.StopServerDiscovery();
            }
        }

        public override void Update() {
            if (UpdatePreviewButton.IsClicked) {
                if (string.IsNullOrEmpty(WorldSeed)) {
                    TrueWorldSeed = Random.Int();
                }
                UpdatePreview();
            }
            if (GameTypeButton.IsClicked) {
                DialogsManager.ShowDialog(
                    this,
                    new ListSelectionDialog(
                        LanguageControl.Get(fName, "3"),
                        Enum.GetValues(typeof(GameType)),
                        128f,
                        o => new GameTypeWidget((GameType)o),
                        delegate(object o) {
                            if (o != null) {
                                publicGameType = (GameType)o;
                            }
                        }
                    )
                );
            }
            if (AILevelButton.IsClicked) {
                IEnumerable<PlayerType> items = from t in Enum.GetValues(typeof(PlayerType)).OfType<PlayerType>()
                    where t != PlayerType.Human
                    select t;
                DialogsManager.ShowDialog(
                    this,
                    new ListSelectionDialog(
                        LanguageControl.Get(PracticeSetupScreen.fName, "11"),
                        items,
                        56f,
                        o => Player.GetPlayerTypeName((PlayerType)o).ToUpper(),
                        delegate(object o) {
                            if (o != null) {
                                AILevel = (PlayerType)o;
                            }
                        }
                    )
                );
            }
            if (ShipRangeButton.IsClicked) {
                Array values = Enum.GetValues(typeof(ShipRange));
                DialogsManager.ShowDialog(
                    this,
                    new ListSelectionDialog(
                        LanguageControl.Get(PracticeSetupScreen.fName, "12"),
                        values,
                        56f,
                        o => Ship.GetShipRangeName((ShipRange)o).ToUpper(),
                        delegate(object o) {
                            if (o != null) {
                                ShipRange = (ShipRange)o;
                            }
                        }
                    )
                );
            }
            if (WorldSeedButton.IsClicked) {
                DialogsManager.ShowDialog(
                    null,
                    new TextBoxDialog(
                        LanguageControl.Get(PracticeSetupScreen.fName, "13"),
                        WorldSeed,
                        12,
                        delegate(string s) {
                            if (s != null) {
                                WorldSeed = s;
                                TrueWorldSeed = GameCreationParameters.CalculateSeed(WorldSeed);
                                UpdatePreview();
                            }
                        }
                    )
                );
            }
            if (PlayButton.IsClicked) {
                NamesManager.EnsureValidPlayerNameExists(
                    delegate {
                        GameCreationParameters creationParameters = new(
                            TrueWorldSeed,
                            (int)PlanetsCountSlider.Value,
                            (int)SpecialPlanetsCountSlider.Value,
                            (int)NeutralsPopulationSlider.Value * 140 / 100,
                            7500 / (int)SpecialEventsSlider.Value,
                            (int)ShipRange,
                            (int)PlayersCountSlider.Value,
                            (int)PlayersCountSlider.Value,
                            9,
                            SettingsManager.Faction,
                            SettingsManager.PlayerName,
                            SettingsManager.PlayerGuid,
                            VersionsManager.Platform,
                            AILevel
                        );
                        if (publicGameType == GameType.Internet) {
                            //DialogsManager.ShowDialog(null, new ConnectingDialog(creationParameters, ConnectingDialog.GameType.Internet));
                            DialogsManager.ShowDialog(null, new SelectLobbyServerDialog(creationParameters));
                        }
                        else {
                            DialogsManager.ShowDialog(this, new ConnectingDialog(creationParameters, ConnectingDialog.GameType.Local));
                        }
                    }
                );
            }
            if (Input.Back
                || BackButton.IsClicked) {
                ScreensManager.SwitchScreen(ScreensManager.PreviousScreen);
            }
            GameTypeButton.Text = GetGameTypeName(publicGameType);
            AILevelButton.Text = Player.GetPlayerTypeName(AILevel).ToUpper();
            ShipRangeButton.Text = Ship.GetShipRangeName(ShipRange).ToUpper();
            WorldSeedButton.Text = string.IsNullOrEmpty(WorldSeed) ? LanguageControl.Get(PracticeSetupScreen.fName, "14") : WorldSeed;
            PlayersCountSlider.Text = PlayersCountSlider.Value.ToString(CultureInfo.InvariantCulture);
            if (PlanetsCountSlider.Value < PlayersCountSlider.Value) {
                PlanetsCountSlider.Value = PlayersCountSlider.Value;
            }
            PlanetsCountSlider.MinValue = PlayersCountSlider.Value;
            PlanetsCountSlider.Text = PlanetsCountSlider.Value.ToString(CultureInfo.InvariantCulture);
            float maxSpecialPlanetsCount = Math.Max(PlanetsCountSlider.Value - PlayersCountSlider.Value, 0f);
            if (SpecialPlanetsCountSlider.Value > maxSpecialPlanetsCount) {
                SpecialPlanetsCountSlider.Value = maxSpecialPlanetsCount;
            }
            SpecialPlanetsCountSlider.MaxValue = maxSpecialPlanetsCount;
            SpecialPlanetsCountSlider.Text = SpecialPlanetsCountSlider.Value.ToString(CultureInfo.InvariantCulture);
            NeutralsPopulationSlider.Text = $"{(int)NeutralsPopulationSlider.Value}%";
            SpecialEventsSlider.Text = $"{(int)SpecialEventsSlider.Value}%";
        }

        public void UpdatePreview() {
            TrueWorldSeedLabel.Text = string.Format(LanguageControl.Get(PracticeSetupScreen.fName, "16"), TrueWorldSeed.ToString());
            PreviewRectangle.Subtexture?.Texture?.Dispose();
            List<StructPlanet> planets = PlanetsModule.GeneratePlanetsList(
                TrueWorldSeed,
                (int)PlanetsCountSlider.Value,
                (int)SpecialPlanetsCountSlider.Value,
                (int)NeutralsPopulationSlider.Value,
                (int)ShipRange,
                GameCreationParameters.GenerateRandomFactions(TrueWorldSeed, SettingsManager.Faction, (int)PlayersCountSlider.Value)
            );
            PreviewRectangle.Subtexture = GameImage.Draw(new Point2(384, 216), planets, true);
        }

        public static string GetGameTypeName(GameType gameType) => LanguageControl.Get(fName, gameType == GameType.Local ? "4" : "5");

        public static string GetGameTypeDescription(GameType gameType) => LanguageControl.Get(fName, gameType == GameType.Local ? "6" : "7");
    }
}